home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DClap / DTableView-c0.cpp < prev    next >
Text File  |  1996-07-05  |  32KB  |  1,324 lines

  1. // DTableView.cp
  2. // d.g.gilbert
  3.  
  4. // this class is used a lot for various display/user interaction arrays of items
  5. // still needs work for multiple selections, run arrays for height/width?
  6. // 
  7.  
  8. #include "DTableView.h"
  9. #include <DPanel.h>
  10. #include <DUtil.h>
  11. #include <DApplication.h>
  12. #include <Dvibrant.h>
  13. #include <DTracker.h>
  14. #include <ncbi.h>
  15. #include <dgg.h>
  16.  
  17.  
  18.  
  19.  
  20. DTabSelector::DTabSelector( DTableView* itsTable)
  21. {
  22.     ITabSelector( itsTable); // in constructor !?
  23. }
  24.  
  25. DTabSelector::~DTabSelector() 
  26. {
  27. #if 0
  28.     fOldSelection= Nlm_DestroyRgn( fOldSelection);
  29.     fNewSelection= Nlm_DestroyRgn( fNewSelection);
  30. #endif
  31. }
  32.  
  33. void DTabSelector::ITabSelector( DTableView* itsTable)
  34. {
  35.     ITracker( cTabSelCmd, itsTable, "selection", true, false, itsTable); 
  36.     // ITracker() calls Reset()
  37. }
  38.  
  39.  
  40. void DTabSelector::Reset()
  41. {
  42.     DTracker::Reset();
  43.     fDoExtend= gKeys->shift();
  44. #if 1
  45.     fOldSelection= ((DTableView*)fView)->GetSelRect();
  46.     fNewSelection= fOldSelection;
  47. #else
  48.     fOldSelection= Nlm_NewRgn(); 
  49.     fNewSelection= Nlm_NewRgn();  
  50.     CopyRgn( ((DTableView*)fView)->fSelections, fOldSelection);
  51.     CopyRgn( fOldSelection, fNewSelection);
  52. #endif
  53. }
  54.  
  55.  
  56. void DTabSelector::DoItWork()  
  57. {
  58.     if (fMovedOnce || fDoExtend) {
  59.         ((DTableView*)fView)->SelectCells( fNewSelection, 
  60.                 fDoExtend, DTableView::kHighlight, DTableView::kSelect);
  61.         }
  62. }
  63.  
  64. void DTabSelector::UndoWork()  
  65. {
  66. #if 1
  67.     Nlm_RecT tmpRect= fNewSelection;
  68.     fNewSelection= fOldSelection;
  69.     fOldSelection= tmpRect;
  70. #else
  71.     Nlm_RgN tmpRgn= fNewSelection;
  72.     fNewSelection= fOldSelection;
  73.     fOldSelection= tmpRgn;
  74. #endif
  75.     DoItWork();
  76. }
  77.  
  78.  
  79. void DTabSelector::DoIt()  
  80. {
  81.     DCommand::DoIt();
  82.     
  83.     Nlm_PoinT pt1, pt2;
  84.     Nlm_RecT    selr;
  85.         // +1 is messy fix to stop left/top -1 creap !
  86.     pt1.x= MIN( fAnchorPoint.x+1, fNextPoint.x);
  87.     pt2.x= MAX( fAnchorPoint.x-1, fNextPoint.x);
  88.     pt1.y= MIN( fAnchorPoint.y+1, fNextPoint.y);
  89.     pt2.y= MAX( fAnchorPoint.y-1, fNextPoint.y);
  90.  
  91.     ((DTableView*)fView)->PointToCell( pt1, selr.top, selr.left);
  92.     ((DTableView*)fView)->PointToCell( pt2, selr.bottom, selr.right);
  93.     selr.bottom++;
  94.     selr.right++;
  95.     fNewSelection= selr;
  96.     if (!fDoExtend) fDoExtend= gKeys->shift(); // give'em another chance to shift
  97.     
  98.     DoItWork();
  99. }
  100.  
  101. void DTabSelector::Undo()  
  102. {
  103.     DCommand::Undo();
  104.     Boolean saveext= fDoExtend;
  105.     fDoExtend= false;
  106.     UndoWork();
  107.     fDoExtend= saveext;
  108. }
  109.  
  110. void DTabSelector::Redo()  
  111. {
  112.     DCommand::Redo();
  113.     UndoWork();
  114. }
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122. //class DTableView : public DPanel
  123.  
  124.  
  125. DTableView::DTableView(long id, DView* itsSuperior, short pixwidth, short pixheight, 
  126.                                                 short nrows, short ncols, short itemwidth, short itemheight,
  127.                                                 Boolean hasVscroll, Boolean hasHscroll):
  128.         DAutoPanel( id, itsSuperior, pixwidth, pixheight, hasVscroll, hasHscroll),
  129.         fItemWidth(itemwidth), fItemHeight(itemheight),
  130.         fTop(0), fLeft(0), fColsDrawn(0), fMaxRows(nrows), fMaxCols(ncols), 
  131.         fSelectedRow(kNoSelection), fSelectedCol(kNoSelection),
  132.         fCanSelectRow(true), fCanSelectCol(false),fIsPrinting(false),
  133.         fWidths(NULL), fHeights(NULL),
  134.         fFont(Nlm_programFont)
  135. {
  136.     Nlm_BaR sb;
  137.     sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  138.   fHasVbar= (sb != NULL);
  139.   sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  140.   fHasHbar= (sb != NULL);
  141.   FindLocation();
  142.   SetTableSize( fMaxRows, fMaxCols);
  143.     SetEmptySelection(false); 
  144.     
  145.     fTabSelector= new DTabSelector( this);
  146.     //fTabSelector->ITabSelector( this);
  147.     fCurrentTracker= fTabSelector;
  148. }
  149.         
  150. DTableView::~DTableView()
  151. {
  152.     MemFree(fWidths);
  153.     MemFree(fHeights);
  154.     //if (fTabSelector) delete fTabSelector; //<< causing Motif crashes !?
  155. }
  156.  
  157. void DTableView::SetCanSelect(Boolean canrow, Boolean cancol)
  158. {
  159.     fCanSelectRow= canrow;
  160.     fCanSelectCol= cancol;
  161. }
  162.  
  163.  
  164. static Boolean didscroll;
  165.  
  166. void DTableView::SelectCells( short row, short col, 
  167.                         Nlm_Boolean extend, Nlm_Boolean highlight, Nlm_Boolean select)
  168. {
  169.     if (row>=fMaxRows || row<0 || col>=fMaxCols || col<0) return;
  170.  
  171.     if (highlight) InvertSelection(); // hide old
  172.     if (fCanSelectRow) fSelectedRow= row; 
  173.     if (fCanSelectCol) fSelectedCol= col;
  174.          
  175.     if (!select) ; // deselect cells !!
  176.     
  177.     if (extend) {
  178.         if (fSelrect.top == kNoSelection) fSelrect.top= row;
  179.         else if (fSelrect.top > row) fSelrect.top= row;
  180.         if (fSelrect.bottom <= row) fSelrect.bottom= row+1; 
  181.     
  182.         if (fSelrect.left == kNoSelection) fSelrect.left= col;
  183.         else if (fSelrect.left > col) fSelrect.left= col;
  184.         if (fSelrect.right <= col) fSelrect.right= col+1; 
  185.         }
  186.     else {
  187.         fSelrect.left= col;
  188.         fSelrect.right= col+1; 
  189.         fSelrect.top= row;
  190.         fSelrect.bottom= row+1; 
  191.         }
  192.         
  193.     didscroll= false;
  194.     ScrollIntoView( fSelrect);
  195.     if (!didscroll && highlight) InvertSelection(); // show new
  196. }
  197.  
  198. void DTableView::SelectCells( Nlm_RecT selrect,  
  199.                         Nlm_Boolean extend, Nlm_Boolean highlight, Nlm_Boolean select)
  200. {
  201.     if (selrect.top>= fMaxRows || selrect.bottom<0 
  202.      || selrect.left>=fMaxCols || selrect.right<0) return;
  203.     selrect.left= Max(0,selrect.left);
  204.     selrect.right= Min(fMaxCols, selrect.right);
  205.     selrect.top= Max(0,selrect.top);
  206.     selrect.bottom= Min(fMaxRows, selrect.bottom);
  207.     
  208.     if (highlight) InvertSelection();  
  209.     if (fCanSelectRow) fSelectedRow= selrect.top; 
  210.     if (fCanSelectCol) fSelectedCol= selrect.left;
  211.     
  212.     if (extend)  {
  213.         if (fSelrect.top == kNoSelection) fSelrect.top= selrect.top;
  214.         if (fSelrect.bottom == kNoSelection) fSelrect.bottom= selrect.bottom;
  215.         if (fSelrect.left == kNoSelection) fSelrect.left= selrect.left;
  216.         if (fSelrect.right == kNoSelection) fSelrect.right= selrect.right;
  217.       Nlm_UnionRect( &fSelrect, &selrect, &fSelrect);
  218.       }
  219.     else   
  220.         fSelrect= selrect; // ?? add +1 to .right & .bottom ??
  221.  
  222.     didscroll= false;
  223.     ScrollIntoView( fSelrect);
  224.     if (!didscroll && highlight) InvertSelection();  
  225. }
  226.  
  227.  
  228. void DTableView::ScrollIntoView(Nlm_RecT itemr)
  229. {
  230.     enum { horizontal= false, vertical= true };
  231.     short    lastitem;
  232.     long    atpix;
  233.     Nlm_BaR sb;
  234.  
  235.      // fItemWidth << this isn't accurate for variable width/height.
  236.     if (fWidths) {
  237.         for (lastitem= fLeft, atpix= 0; lastitem< fMaxCols; lastitem++) { 
  238.             atpix += fWidths[lastitem]; 
  239.             if (atpix > fRect.right) break;
  240.             }
  241.         }
  242.     else
  243.         lastitem= fLeft + (fRect.right - fRect.left)/fItemWidth;
  244.      
  245.     if (itemr.left > lastitem || itemr.left < fLeft) {
  246.          didscroll= true;
  247.         sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  248.         if (sb) { 
  249.             //Nlm_ResetClip(); // ! TEST: are we losing scrollbar update due to cliprect?
  250.             Nlm_SetValue(sb, Max(0, itemr.left - 1));  // calls our scroll funct
  251.             }
  252.         }
  253.     
  254.     if (fHeights) {
  255.         for (lastitem= fTop, atpix= 0; lastitem< fMaxRows; lastitem++) { 
  256.             atpix += fHeights[lastitem]; 
  257.             if (atpix > fRect.bottom) break;
  258.             }
  259.         }
  260.     else
  261.         lastitem= fTop + (fRect.bottom - fRect.top)/fItemHeight;
  262.         
  263.     if (itemr.top > lastitem || itemr.top < fTop) {
  264.          didscroll= true;
  265.         sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  266.         if (sb) Nlm_SetValue(sb,  Max(0, itemr.top - 1));  
  267.         }
  268. }
  269.  
  270.  
  271. void DTableView::SetEmptySelection(Boolean redraw)
  272. {
  273.     if (redraw) {
  274.         //InvertSelection();
  275.         InvalidateSelection();
  276.         }
  277.     fSelectedRow = kNoSelection;
  278.     fSelectedCol = kNoSelection;
  279.     //Nlm_SetRect
  280.     Nlm_LoadRect( &fSelrect, kNoSelection, kNoSelection, kNoSelection, kNoSelection);
  281. }
  282.  
  283. void DTableView::InvalidateSelection()
  284. {
  285.     Nlm_RecT r, r2;
  286.     if (!Nlm_EmptyRect(&fSelrect)) {
  287.         r2= fSelrect;
  288.         GetCellRect( r2, r);
  289.         InvalRect( r);
  290.         }
  291.     else if (fSelectedRow>=0 && fSelectedCol>=0) {
  292.         GetCellRect( fSelectedRow, fSelectedCol, r);
  293.         InvalRect( r);
  294.         }
  295.     else if (fSelectedRow>=0) {
  296.         GetRowRect( fSelectedRow, r);
  297.         InvalRect( r);
  298.         }
  299.     else if (fSelectedCol>=0) {
  300.         GetRowRect( fSelectedCol, r);
  301.         InvalRect( r);
  302.         }
  303. }
  304.  
  305.  
  306. Boolean DTableView::IsSelected()
  307. {
  308.     return (!Nlm_EmptyRect( &fSelrect));
  309.     //return (fSelectedRow == kNoSelection && fSelectedCol == kNoSelection);
  310.  
  311.  
  312. Boolean DTableView::IsSelected(short row, short col)
  313. {
  314.     Nlm_PoinT pt;
  315.     pt.y= row; pt.x= col;
  316.     Boolean issel= Nlm_PtInRect( pt, &fSelrect);
  317.     return issel;
  318. }  
  319.  
  320.  
  321.  
  322.  
  323. void DTableView::SetTableFont( Nlm_FonT itsFont)
  324. {
  325.     fFont= itsFont;
  326. }
  327.  
  328. void DTableView::SetTableSize( short rows, short cols)
  329. {
  330.     short i;
  331.     
  332.     if (fWidths && cols!=fMaxCols) {
  333.         fWidths= (short*)MemMore( fWidths, (cols+1) * sizeof(short));
  334.         for (i= fMaxCols; i<=cols; i++) fWidths[i]= fItemWidth;
  335.         }
  336.         
  337.     if (fHeights && rows!=fMaxRows) {
  338.         fHeights= (short*)MemMore( fHeights, (rows+1) * sizeof(short));
  339.         for (i= fMaxRows; i<=rows; i++) fHeights[i]= fItemHeight;
  340.         }
  341.     
  342.     fMaxRows= rows; 
  343.     fMaxCols= cols;
  344.  
  345.     SetScrollPage();
  346. }
  347.  
  348. void DTableView::ChangeRowSize( short atrow, short deltarows)
  349. {
  350.     Boolean needupdate;
  351.     short newrows= Max(0, fMaxRows + deltarows);
  352. #if 1
  353.     Nlm_RecT  r;
  354.     ViewRect(fRect); 
  355.     Nlm_InsetRect( &fRect, 1, 1);
  356.     GetRowRect( atrow, r, (fMaxRows - atrow));
  357.     needupdate= Nlm_SectRect( &r, &fRect, &r);
  358.     SetTableSize( newrows, fMaxCols);
  359.     if (needupdate) this->InvalRect( r);
  360. #else
  361.     short viewrows=  (fRect.bottom - fRect.top) / fItemHeight;
  362.     needupdate= (atrow >= fTop && atrow <= viewrows);
  363.         // ^^ needs work
  364.     SetTableSize( newrows, fMaxCols);
  365.     if (needupdate) {
  366.         //this->Invalidate(); // locate just update rect??    
  367.         Nlm_RecT r;
  368.         short nrows= viewrows - atrow;
  369.         GetRowRect( atrow, r, nrows);
  370.         this->InvalRect( r);
  371.         }
  372. #endif
  373. }
  374.  
  375. void DTableView::ChangeColSize( short atcol, short deltacols)
  376. {
  377.     short newcols= Max(0, fMaxCols + deltacols);
  378.     Boolean needupdate= (atcol >= fLeft && atcol <= (fRect.right - fRect.left) / fItemWidth);
  379.         // ^^ needs work
  380.     SetTableSize( fMaxRows, newcols);
  381.     if (needupdate) {
  382.         //this->Invalidate(); // locate just update rect??    
  383.         Nlm_RecT r;
  384.         short ncols= ((fRect.right - fRect.left) / fItemWidth) - atcol;
  385.         GetColRect( atcol, r, ncols);
  386.         this->InvalRect( r);
  387.         }
  388. }
  389.  
  390.         
  391. void DTableView::SetItemWidth(short atcol, short ncols, short itemwidth)
  392. {
  393.     short i;
  394.     if (ncols >= fMaxCols && !fWidths) {
  395.         fItemWidth= itemwidth;
  396.         }
  397.     else {
  398.         if (!fWidths) {
  399.             // make fWidths
  400.             fWidths= (short*)MemNew( (fMaxCols+1)*sizeof(short));
  401.             for (i= 0; i<=fMaxCols; i++) fWidths[i]= fItemWidth;
  402.             }
  403.         short ncol= Min(fMaxCols, atcol+ncols);
  404.         for (i= atcol; i<ncol; i++) fWidths[i]= itemwidth;
  405.     fItemWidth= Max( fItemWidth, itemwidth);
  406.         }
  407.   SetScrollPage();
  408. }
  409.  
  410. void DTableView::SetItemHeight(short atrow, short nrows, short itemheight)
  411. {
  412.     short i;
  413.     if (nrows >= fMaxRows && !fHeights) {
  414.         fItemHeight= itemheight;
  415.         }
  416.     else {
  417.         if (!fHeights) {
  418.             fHeights= (short*)MemNew( (fMaxRows+1)*sizeof(short));
  419.             for (i= 0; i<=fMaxRows; i++) fHeights[i]= fItemHeight;
  420.             }
  421.         short nrow= Min(fMaxRows, atrow+nrows);
  422.         for (i= atrow; i<nrow; i++) fHeights[i]= itemheight;
  423. #if 0
  424.     if (itemheight) fItemHeight= MIN( fItemHeight, itemheight);
  425. #else
  426.     fItemHeight= MAX( fItemHeight, itemheight);
  427. #endif
  428.         }
  429.   SetScrollPage();
  430. }
  431.         
  432. void DTableView::SetScrollPage()
  433. {
  434.     // set paging size of hor/vert sbars.. need to do on open & on resize
  435.     Nlm_BaR sb;
  436.     short pgDn, pg, maxn;
  437.     if (fHasHbar) {
  438.         pg= (fRect.right - fRect.left) / fItemWidth;
  439.         pgDn= Max(1, pg - 1);
  440.         maxn= Max( fMaxCols - pgDn, 1);
  441.         sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  442.         if (sb) Nlm_SetRange(sb, pgDn, pgDn, maxn);
  443.         }
  444.     if (fHasVbar) {
  445.         pg= (fRect.bottom - fRect.top) / fItemHeight;
  446.         pgDn= Max(1, pg - 1);
  447.         maxn= Max( fMaxRows - pgDn, 1);
  448.         sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  449.         if (sb) Nlm_SetRange(sb, pgDn, pgDn, maxn);
  450.         }
  451. }
  452.  
  453. void DTableView::FindLocation()
  454. {
  455.     ViewRect(fRect); //this->GetPosition(fRect); // ?? this isn't changing except w/ resize ??
  456.     Nlm_InsetRect( &fRect, 1, 1);
  457.     SetScrollPage();
  458. }
  459.         
  460. void DTableView::SizeToSuperview( DView* super, Boolean horiz, Boolean vert)
  461. {
  462. #ifndef WIN_MSWIN
  463.     DView::SizeToSuperview(super, horiz, vert);
  464. #else
  465.     Nlm_RecT r, myr;
  466.     super->ViewRect(r);
  467.     ViewRect(myr);
  468.             // these sizes draw off by -1... thus the +1
  469.     if (horiz) {
  470.         myr.left = 0;
  471.         myr.right= myr.left + (r.right - r.left) +1;
  472. #ifdef WIN_MSWIN
  473.         if (fHasVbar) myr.right -= (Nlm_vScrollBarWidth - 8);
  474. #endif
  475.         }
  476.     if (vert) {
  477.         myr.top = 0;
  478.         myr.bottom = myr.top + (r.bottom - r.top) +1;
  479. #ifdef WIN_MSWIN
  480.         if (fHasHbar) myr.bottom -= (Nlm_hScrollBarHeight + 10);
  481. #endif
  482.         }
  483.     SetPosition( myr);
  484. #endif
  485.     this->FindLocation(); //?? added 14Mar94, gopher tables were doing this
  486. }
  487.  
  488.  
  489. void DTableView::Resize(DView* superview, Nlm_PoinT sizechange)
  490. {
  491.         // !! need this fRect change to deal w/ Resize() update event, 
  492.         // which isn't put in a nice event queue, but is done immediately !!
  493.     fRect.right  += sizechange.x;
  494.     fRect.bottom += sizechange.y;
  495.     DPanel::Resize(superview, sizechange);
  496.     FindLocation();
  497. }
  498.  
  499. void DTableView::Scroll(Boolean vertical, DView* scrollee, short newval, short oldval)
  500. {
  501.     Nlm_RecT    r = fRect;
  502.     short delta, i;
  503.     short diff= newval-oldval;
  504.     this->Select(); // need for motif !
  505.     if (vertical) {
  506.  
  507.       if (fHeights) {
  508.         delta= 0;
  509.             if (oldval>newval) {
  510.                 for (i=oldval-1; i>=newval; i--) delta -= fHeights[i];
  511.                 }
  512.         else {
  513.                 for (i=oldval; i<newval; i++) delta += fHeights[i];
  514.                 }
  515.             }
  516.         else
  517.             delta= diff * fItemHeight;
  518.  
  519.         fTop += diff;
  520.         Nlm_ScrollRect (&r, 0, -delta);
  521.         if (diff<0) r.bottom= r.top - delta + Min(10,-delta/2);
  522.         else r.top= r.bottom - delta - Min(10,delta/2);
  523.         }
  524.         
  525.     else {
  526. #if 1
  527.       if (fWidths) {
  528.         delta= 0;
  529.             if (oldval>newval) {
  530.                 for (i=oldval-1; i>=newval; i--) delta -= fWidths[i];
  531.                 }
  532.         else {
  533.                 for (i=oldval; i<newval; i++) delta += fWidths[i];
  534.                 }
  535.             }
  536.         else
  537.             delta= diff * fItemWidth;
  538.             
  539.         fLeft += diff;
  540.         Nlm_ScrollRect (&r, -delta, 0);
  541.         if (diff<0) r.right= Min(r.right, r.left - delta + Min(20,-delta/2));
  542.         else r.left= Max(r.left, r.right - delta - Min(20,delta/2));
  543. #else
  544.         if (fWidths) {
  545.             // fix later, for now redraw all w/o bitscroll
  546.             fLeft += diff;
  547.             }
  548.         else {
  549.             fLeft += diff;
  550.             delta= diff * fItemWidth;
  551.             Nlm_ScrollRect (&r, -delta, 0);
  552.             if (diff<0) r.right= r.left - delta + Min(10,-delta/2);
  553.             else r.left= r.right - delta - Min(10,delta/2);
  554.             }
  555. #endif
  556.         }
  557.     this->InvalRect( r);
  558.   Nlm_Update(); //!? need since took out vibwnds autoupdate for RestorePort
  559. }
  560.             
  561.  
  562. void DTableView::GetRowRect( short row, Nlm_RecT& r, short nrows)
  563. {
  564.     short i;
  565.     r= fRect;
  566.     if (fHeights) {
  567.         for (i= fTop; i<row; i++) r.top += fHeights[i];
  568.         r.bottom= r.top;
  569.         for (i= 0; i<nrows; i++) r.bottom += fHeights[row+i];
  570.         }
  571.     else {
  572.         r.top += (row-fTop) * fItemHeight;
  573.         r.bottom = r.top + nrows*fItemHeight;
  574.         }
  575. }
  576.  
  577. void DTableView::GetColRect( short col, Nlm_RecT& r, short ncols)
  578. {
  579.     short i;
  580.     r= fRect;
  581.     if (fWidths) {
  582.         for (i= fLeft; i<col; i++) r.left += fWidths[i];
  583.         r.right= r.left;
  584.         for (i= 0; i<ncols; i++) r.right += fWidths[col+i];
  585.         }
  586.     else {
  587.         r.left += (col-fLeft) * fItemWidth;
  588.         r.right = r.left + ncols*fItemWidth;
  589.         }
  590. }
  591.  
  592. void DTableView::GetCellRect( short row, short col, Nlm_RecT& r)
  593. {
  594.     short i;
  595.     r= fRect;
  596.     if (fWidths) {
  597.         for (i= fLeft; i<col; i++) r.left += fWidths[i];
  598.         r.right= r.left + fWidths[col];
  599.         }
  600.     else {
  601.         r.left += (col-fLeft) * fItemWidth;
  602.         r.right = r.left + fItemWidth;
  603.         }
  604.     if (fHeights) {
  605.         for (i= fTop; i<row; i++) r.top += fHeights[i];
  606.         r.bottom= r.top + fHeights[row];
  607.         }
  608.     else {
  609.         r.top += (row-fTop) * fItemHeight;
  610.         r.bottom = r.top + fItemHeight;
  611.         }
  612. }
  613.  
  614. void DTableView::GetCellRect(Nlm_RecT cellr, Nlm_RecT& r)
  615. {
  616.     short i;
  617.     r= fRect;
  618.     if (fWidths) {
  619.         for (i= fLeft; i<cellr.left; i++) r.left += fWidths[i];
  620.         r.right= r.left;
  621.         for (i=cellr.left; i<cellr.right; i++) r.right += fWidths[i];
  622.         }
  623.     else {
  624.         r.left += (cellr.left-fLeft) * fItemWidth;
  625.         r.right = r.left + (cellr.right - cellr.left) * fItemWidth;
  626.         }
  627.         
  628.     if (fHeights) {
  629.         for (i= fTop; i<cellr.top; i++) r.top += fHeights[i];
  630.         r.bottom= r.top;
  631.         for (i=cellr.top; i<cellr.bottom; i++) r.bottom += fHeights[i];
  632.         }
  633.     else {
  634.         r.top += (cellr.top-fTop) * fItemHeight;
  635.         r.bottom = r.top + (cellr.bottom - cellr.top) * fItemHeight;
  636.         }
  637. }
  638.  
  639.     
  640. short DTableView::GetSelectedRow()
  641.     return fSelectedRow; 
  642. }
  643.  
  644. short DTableView::GetSelectedCol() 
  645.     return fSelectedCol; 
  646. }
  647.  
  648. void DTableView::GetFirstSelectedCell( short& row, short& col)
  649. #if 0
  650.     row= fSelectedRow; 
  651.     col= fSelectedCol; 
  652. #else
  653.     row= fSelrect.top;
  654.     col= fSelrect.left;
  655. #endif
  656. }
  657.  
  658. void DTableView::GetLastSelectedCell( short& row, short& col)
  659. #if 0
  660.     row= fSelectedRow; 
  661.     col= fSelectedCol; 
  662. #else
  663.     row= fSelrect.bottom;
  664.     col= fSelrect.right;
  665. #endif
  666. }
  667.     
  668.  
  669.  
  670. #ifdef WIN_MOTIF
  671.  
  672. #include <ncbi.h>
  673. #include <ncbidraw.h>
  674. //typedef unsigned long XID; // this is failing in X.h !?
  675. //#define XID  unsigned long
  676. #include <ncbiwin.h>
  677. #include <ncbiport.h>
  678.  
  679. extern Display      *Nlm_currentXDisplay;
  680. extern int          Nlm_currentXScreen;
  681. extern Window       Nlm_currentXWindow;
  682. extern GC           Nlm_currentXGC;
  683. extern Nlm_Uint4    Nlm_XbackColor;
  684. extern Nlm_Uint4    Nlm_XforeColor;
  685. extern Nlm_Int2     Nlm_XOffset;
  686. extern Nlm_Int2     Nlm_YOffset;
  687. extern Nlm_RegioN   Nlm_clpRgn;
  688.  
  689. #endif
  690.  
  691.  
  692. inline void DTableInvertRect( Nlm_RecT& r)
  693. {    
  694. #ifdef notWIN_MOTIF
  695. // vals: GXcopy  GXand  GXor GXequiv GXinvert GXorInverted
  696. // !! GXor looks GOOD for colored x -- makes gray rect
  697. // but isn't reverting to regular on deselect, unless click is in selrect !?? 
  698. // GXxor looks okay at start, but repeated calls mess it up (conflict??)
  699. // fill vals: FillStippled  FillOpaqueStippled  FillSolid  FillTiled
  700.  
  701. #define newfunc  GXxor
  702. #define currentFunction  GXcopy
  703. #define newfill  FillStippled
  704. #define currentFillStyle   FillStippled
  705.   Nlm_RectTool  rtool;
  706.  
  707. #if 1
  708.   if (Nlm_currentXDisplay && Nlm_currentXWindow && Nlm_currentXGC) {
  709.     rtool.x = MIN (r.left, r.right);
  710.     rtool.y = MIN (r.top, r.bottom);
  711.     rtool.width = ABS (r.right - r.left);
  712.     rtool.height = ABS (r.bottom - r.top);
  713.  
  714.         // ! recommended by Xlib vol 1, sect. 7.4.3: foreground( forecol ^ backcol)
  715.         // ! and it works !
  716.         ulong xorcolor= Nlm_XforeColor ^ Nlm_XbackColor;
  717.         XSetForeground( Nlm_currentXDisplay,Nlm_currentXGC, xorcolor);
  718.     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, newfunc);
  719.     //XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, newfill);
  720.     XFillRectangle (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
  721.                     rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
  722.                     rtool.width, rtool.height);
  723.     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
  724.     //XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
  725.         XSetForeground( Nlm_currentXDisplay,Nlm_currentXGC, Nlm_XforeColor);
  726.    }
  727.  
  728. #else
  729.     Nlm_InvertMode();
  730.     Nlm_PaintRect( &r);
  731.     Nlm_CopyMode();
  732. #endif
  733.  
  734. #else
  735.     // patched both Nlm_InvertMode & Nlm_InvertRect for Motif
  736.   Nlm_InvertRect( &r);
  737. #endif 
  738. }
  739.  
  740. void DTableView::InvertRect( Nlm_RecT& r)
  741. {    
  742.     Nlm_WindoW w= Nlm_SavePort( fNlmObject);
  743. #ifdef WIN_MOTIF
  744.     this->Select();
  745. #endif
  746.     ::DTableInvertRect( r);
  747.     if (w) Nlm_UseWindow (w); 
  748. }
  749.  
  750. void DTableView::InvertSelection()
  751. {    
  752.     Nlm_RecT r, r2;
  753.     if (!Nlm_EmptyRect(&fSelrect)) {
  754.         r2= fSelrect;
  755.         //r2.bottom--;
  756.         //r2.right--;
  757.         GetCellRect( r2, r);
  758.         }
  759.     else if (fSelectedRow>=0 && fSelectedCol>=0) 
  760.         GetCellRect( fSelectedRow, fSelectedCol, r);
  761.     else if (fSelectedRow>=0) 
  762.         GetRowRect( fSelectedRow, r);
  763.     else if (fSelectedCol>=0) 
  764.         GetRowRect( fSelectedCol, r);
  765.   else
  766.       return;
  767.     InvertRect( r);
  768. }
  769.  
  770.  
  771.  
  772. void DTableView::DoubleClickAt(short row, short col)
  773. {
  774. }
  775.  
  776.  
  777. void DTableView::SingleClickAt(short row, short col)
  778. {
  779.     Nlm_PoinT pt;
  780.     pt.x= col; pt.y= row;
  781.     if (Nlm_PtInRect( pt, &fSelrect) && !gKeys->shift()) {
  782.         SetEmptySelection( true);
  783.         }
  784.     else {
  785.         SelectCells(  row, col, gKeys->shift(), kHighlight, kSelect);
  786.         }
  787. }
  788.             
  789.  
  790. void DTableView::PointToCell(Nlm_PoinT mouse, short& row, short& col)
  791. {
  792.     if (fHeights) {
  793.         row= fTop - 1;
  794.         short yrow= fRect.top;
  795.         do {
  796.             row++;
  797.             if (row<=fMaxRows) yrow += fHeights[row];
  798.             else yrow= mouse.y;
  799.             } while (yrow < mouse.y);
  800.         }
  801.     else
  802.         row= fTop  + (mouse.y - fRect.top)  / fItemHeight;
  803.  
  804.     if (fWidths) {
  805.         col= fLeft - 1;
  806.         short xcol= fRect.left;
  807.         do {
  808.             col++;
  809.             if (col<=fMaxCols) xcol += fWidths[col];
  810.             else xcol= mouse.x;
  811.             } while (xcol < mouse.x);
  812.         }
  813.     else
  814.         col= fLeft + (mouse.x - fRect.left) / fItemWidth;
  815. }
  816.  
  817.  
  818.  
  819. void DTableView::Click(Nlm_PoinT mouse)
  820. {
  821.     short row, col;
  822.     
  823.     //if (gLastCommand) gLastCommand->Commit();    //?? prevent bombs from prev. cmds ?
  824.     //if (fCurrentTracker) fCurrentTracker->Reset();
  825.     SetTracker( fCurrentTracker); // ??  make new one each click?
  826.     DAutoPanel::Click(mouse);         // sets fMouseStillDown= false
  827.  
  828.     if (!fCurrentTracker) {
  829.         // TrackMouse::trackEnd does this now, if click is tracked...
  830.         PointToCell( mouse, row, col);
  831.         if (row >=0 && row < fMaxRows && col >= 0 && col < fMaxCols) {
  832.             if (Nlm_dblClick) DoubleClickAt( row, col);
  833.             else SingleClickAt( row, col);
  834.             }
  835.         }
  836. }
  837.  
  838. void DTableView::Drag(Nlm_PoinT mouse)
  839. {
  840.     DAutoPanel::Drag(mouse); // sets fMouseStillDown= true,... 
  841. }
  842.  
  843. void DTableView::Release(Nlm_PoinT mouse)
  844. {
  845.     DAutoPanel::Release(mouse); // sets fMouseStillDown= false,... 
  846. }
  847.  
  848.  
  849. void DTableView::TrackMouse( short aTrackPhase,
  850.                     Nlm_PoinT& anchorPoint, Nlm_PoinT& previousPoint,
  851.                     Nlm_PoinT& nextPoint,    Nlm_Boolean mouseDidMove)
  852. {
  853.  
  854.     switch (aTrackPhase) {
  855.     
  856.         case DTracker::trackBegin:
  857.             if (gKeys->shift()) {  
  858.                 Nlm_PoinT pt;
  859.                 Nlm_RecT  pixr;
  860.                 short    diff1, diff2;
  861.                 
  862.                 GetCellRect( fSelrect, pixr);
  863.                 diff1= anchorPoint.x - pixr.left;
  864.                 diff2= anchorPoint.x - pixr.right;
  865.                 if (abs(diff1) > abs(diff2)) pt.x= pixr.left; 
  866.                 else pt.x= pixr.right;
  867.                 diff1= anchorPoint.y - pixr.top;
  868.                 diff2= anchorPoint.y - pixr.bottom;
  869.                 if (abs(diff1) > abs(diff2)) pt.y= pixr.top; 
  870.                 else pt.y= pixr.bottom;
  871.                 
  872.                 // tracker::Start makes 3 pts all same
  873.                 anchorPoint = pt;
  874.                 previousPoint = pt;
  875.                 nextPoint = pt;
  876.                 //fTracker->fMovedOnce= true; // force it for single-click extend?
  877.                 }
  878.              break;
  879.     
  880.         case DTracker::trackContinue:
  881.             break;
  882.             
  883.         case DTracker::trackEnd:
  884.             {
  885.             short row, col;
  886.             Boolean moved= gKeys->shift() // extend
  887.                     || abs(anchorPoint.x - nextPoint.x) > 2
  888.                     || abs(anchorPoint.y - nextPoint.y) > 2;
  889.             if (!moved) {
  890.                 PointToCell( nextPoint, row, col);
  891.                 if (row >=0 && row < fMaxRows && col >= 0 && col < fMaxCols) {
  892.                     if (Nlm_dblClick) DoubleClickAt( row, col);
  893.                     else SingleClickAt( row, col);
  894.                     }
  895.                 }
  896.             }
  897.             break;
  898.             
  899.         }
  900. }
  901.  
  902. void DTableView::TrackFeedback( short aTrackPhase,
  903.                     const Nlm_PoinT& anchorPoint, const Nlm_PoinT& previousPoint,
  904.                     const Nlm_PoinT& nextPoint, Nlm_Boolean mouseDidMove, Nlm_Boolean turnItOn)
  905. {
  906.     if (mouseDidMove) {
  907.         Nlm_RecT    pixr;
  908.  
  909.         pixr.left= MIN( anchorPoint.x, nextPoint.x);
  910.         pixr.right= MAX( anchorPoint.x, nextPoint.x);
  911.         pixr.top= MIN( anchorPoint.y, nextPoint.y);
  912.         pixr.bottom= MAX( anchorPoint.y, nextPoint.y);
  913.         
  914.         Nlm_InsetRect( &pixr, 1,1); //??
  915.         Nlm_InvertMode();
  916.         Nlm_FrameRect( &pixr);
  917.         Nlm_CopyMode();
  918.         }
  919. }
  920.  
  921.  
  922.  
  923.  
  924. void DTableView::DrawCell(Nlm_RecT r, short row, short col)
  925. {
  926.     char    snum[80];
  927.     sprintf(snum,"r%d,c%d", row, col);
  928.     Nlm_DrawString( &r, snum, 'c', false);
  929. }
  930.     
  931. void DTableView::DrawRow(Nlm_RecT r, short row)
  932. {
  933.     short col = fLeft; 
  934.     if (fWidths && col <= fMaxCols) r.right= r.left + fWidths[col];
  935.     else r.right= r.left + fItemWidth;
  936.     while (r.left < fRect.right && col < fMaxCols) {
  937.         if (Nlm_RectInRgn (&r, Nlm_updateRgn))  
  938.             DrawCell( r, row, col);
  939.         if (fWidths) {
  940.             Nlm_OffsetRect( &r, fWidths[col], 0);
  941.             r.right= r.left + fWidths[col+1];
  942.             }
  943.         else
  944.             Nlm_OffsetRect( &r, fItemWidth, 0);
  945.         col++;
  946.         }
  947.     fColsDrawn= col - fLeft;
  948. }
  949.  
  950.  
  951. void DTableView::GetPageCount(Nlm_RecT pagerect, short& rowpages, short& colpages)
  952. {
  953.     long left, top, row, col;     
  954.     rowpages= colpages= 1;
  955.     
  956.     for (col=0, left=0; col < fMaxCols; col++) {
  957.         if (fWidths) left += fWidths[col];  
  958.         else left += fItemWidth;
  959.         if (left >= pagerect.right) { 
  960.             colpages++; 
  961.             left= 0; 
  962.             }
  963.         }
  964.     for (row=0, top=0; row < fMaxRows; row++) {
  965.         if (fHeights) top += fHeights[row];  
  966.         else top += fItemHeight;
  967.         if (top >= pagerect.bottom) { 
  968.             rowpages++; 
  969.             top= 0; 
  970.             }
  971.         }
  972. }
  973.  
  974.  
  975. void DTableView::Draw()
  976. {
  977.     Nlm_RecT         r2, r = fRect;
  978.     Nlm_PoinT      pt;
  979.     short             row = fTop; 
  980.     Boolean            hasSel;
  981.     
  982.     if (fHeights) r.bottom= r.top + fHeights[row];
  983.     else r.bottom= r.top + fItemHeight;
  984.     Nlm_SelectFont(fFont); //?? here
  985.     hasSel= !Nlm_EmptyRect(&fSelrect);
  986.     if (hasSel) {
  987.         pt.x= fSelrect.left;
  988.         r2= fSelrect;
  989.         GetCellRect( r2, r2);
  990.         }
  991.         
  992.     while (r.top < fRect.bottom && row < fMaxRows) {
  993.         if (Nlm_RectInRgn (&r, Nlm_updateRgn)) { 
  994.             DrawRow( r, row);
  995.              pt.y= row;
  996.              if (hasSel && Nlm_PtInRect( pt, &fSelrect)) {
  997.                  Nlm_RecT ir= r;
  998.                  ir.left= r2.left;
  999.                  ir.right= r2.right;
  1000.                 InvertRect( ir);
  1001.                  }
  1002.           }
  1003.         if (fHeights) {
  1004.             Nlm_OffsetRect( &r, 0, fHeights[row]);
  1005.             r.bottom= r.top + fHeights[row+1];
  1006.             }
  1007.         else
  1008.             Nlm_OffsetRect( &r, 0, fItemHeight);
  1009.         row++;
  1010.         }
  1011. }
  1012.         
  1013.  
  1014. enum { kWritingAsPICT = 9 };
  1015.  
  1016. void DTableView::ViewRect(Nlm_RecT& r) 
  1017.     if (fIsPrinting == kWritingAsPICT) {
  1018.         r= fRect; // fRect is set at start of AsPICT
  1019.         }
  1020.     else if (fIsPrinting) {
  1021.         r= fRect; //fRect is set at start of Print 
  1022.         // Nlm_PrintingRect(&r);
  1023.         }
  1024.     else
  1025.         DView::ViewRect(r);  
  1026. }
  1027.         
  1028. void DTableView::Print()  
  1029. {
  1030. #if (defined(WIN_MAC) || defined (WIN_MSWIN))
  1031.   Nlm_WindoW    w;
  1032.   Boolean           goOn, newPage, widerThanPage;
  1033.   Nlm_RecT        pager, r, saverect;
  1034.     short                 row = 0, rowpages, colpages; 
  1035.     long                    saveleft;
  1036.     
  1037.     // problems: assumes each row < page height
  1038.     
  1039.   w = Nlm_StartPrinting();
  1040.   if (w) {
  1041.       fIsPrinting= true;
  1042.         gCursor->watch();    
  1043.         saverect= fRect;
  1044.         Nlm_PrintingRect(&pager);
  1045.         fRect= pager;
  1046.         Nlm_SelectFont(fFont); 
  1047.         saveleft= fLeft; fLeft= 0; 
  1048.         //savetop= fTop; fTop= 0; 
  1049.         GetPageCount( pager, rowpages, colpages);
  1050.         
  1051.     newPage = true;
  1052.     goOn = row < fMaxRows;
  1053.     widerThanPage= colpages > 1; 
  1054.     
  1055.     // make update region large...
  1056.     if (Nlm_updateRgn != NULL)  
  1057.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1058.     
  1059.     while (goOn) {
  1060.     
  1061.       if (newPage) {
  1062.         goOn = Nlm_StartPage();
  1063.         newPage = false;
  1064.           r= pager;
  1065.           
  1066.                 if (fHeights) r.bottom= r.top + fHeights[row];
  1067.                 else r.bottom= r.top + fItemHeight;
  1068.            }
  1069.       
  1070.       if (goOn) {
  1071.                 fColsDrawn= fMaxCols; // in case DrawRow forgets to set this
  1072.                 DrawRow( r, row);
  1073.                 
  1074.                 if (widerThanPage) {
  1075.                   fLeft +=     fColsDrawn;
  1076.                     newPage = (fLeft < fMaxCols);
  1077.                     if (newPage) goOn = Nlm_EndPage();    
  1078.                     else fLeft= 0;
  1079.                     }
  1080.                 
  1081.                 if (!newPage) {    
  1082.                     if (fHeights) {
  1083.                         Nlm_OffsetRect( &r, 0, fHeights[row]);
  1084.                         r.bottom= r.top + fHeights[row+1];
  1085.                         }
  1086.                     else
  1087.                         Nlm_OffsetRect( &r, 0, fItemHeight);
  1088.                     newPage = (r.bottom > pager.bottom);
  1089.                     if (newPage) goOn = Nlm_EndPage();    
  1090.                     row++;
  1091.                     if (goOn) goOn= (row < fMaxRows);
  1092.                     }
  1093.                     
  1094.                 }
  1095.             }
  1096.             
  1097.           if (!newPage) (void) Nlm_EndPage();
  1098.       Nlm_EndPrinting(w);
  1099.         fIsPrinting= false;
  1100.         fRect= saverect;
  1101.         fLeft= saveleft;
  1102.         gCursor->arrow();
  1103.         }       
  1104. #else
  1105.     Nlm_Message(MSG_OK,"Printing is not yet defined for this window system");
  1106. #endif
  1107. }
  1108.  
  1109.  
  1110. #ifdef WIN_MAC
  1111. #undef Handle
  1112. #undef Rect
  1113. #include <QuickDraw.h>
  1114. #include <Memory.h>
  1115. #endif
  1116.  
  1117. #ifdef WIN_MSWIN
  1118. #undef FAR 
  1119. #undef NEAR 
  1120. #include <windows.h>
  1121. extern "C" HWND         Nlm_currentHWnd;
  1122. extern "C" HDC          Nlm_currentHDC;
  1123.  
  1124. struct METAFILEHEADER { // must be 22 bytes !
  1125.     DWORD    key;
  1126.     WORD    hmf; // HANDLE hmf; for Win16 !
  1127.     //RECT    bbox; for Win16 !
  1128.     WORD  boxleft;
  1129.     WORD  boxtop;
  1130.     WORD  boxright;
  1131.     WORD  boxbottom;
  1132.     WORD    inch;
  1133.     DWORD    reserved;
  1134.     WORD    checksum;
  1135. };
  1136.  
  1137.       
  1138. void CalcMFChecksum(METAFILEHEADER* pMFHead)
  1139. {
  1140.   WORD *p;
  1141.  
  1142.   for (p =(WORD *)pMFHead, pMFHead->checksum = 0;
  1143.          p < (WORD *)&pMFHead->checksum; ++p)
  1144.          pMFHead->checksum ^= *p;
  1145. }
  1146.  
  1147. #endif
  1148.  
  1149. void DTableView::WriteToPICT(DFile* afile)  
  1150. {
  1151.     if (!afile) return;
  1152.     
  1153. #ifdef WIN_MAC
  1154.   Nlm_RecT        pager, saverect, cellr;
  1155.     
  1156.     gCursor->watch();    
  1157.     saverect= fRect;
  1158.      fIsPrinting= kWritingAsPICT;
  1159.      Nlm_LoadRect( &cellr, 0, 0, fMaxCols, fMaxRows);
  1160.     this->GetCellRect( cellr, pager);
  1161.     fRect= pager;
  1162.     
  1163.   Rect  picrect;
  1164.   picrect.left= pager.left;
  1165.   picrect.right= pager.right;
  1166.   picrect.top = pager.top;
  1167.   picrect.bottom= pager.bottom;
  1168.     Handle pic= (Handle) OpenPicture( &picrect); 
  1169.     
  1170.   if (pic) { 
  1171.       enum { kPicHeadsize = 512 };
  1172.       ulong count;
  1173.         // make update region large...
  1174.     if (Nlm_updateRgn != NULL)  
  1175.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1176.     Draw();                
  1177.       ClosePicture();
  1178.       
  1179.           // now write pic to file
  1180.       afile->Delete();
  1181.       afile->Create("PICT","ttxt"); 
  1182.         afile->Open("wb"); // Damn "wb" -- must by BINARY 
  1183.       count= kPicHeadsize;
  1184.       char * header = (char *) Nlm_MemGet(kPicHeadsize,MGET_CLEAR);
  1185.       afile->WriteData( header, count);
  1186.       Nlm_MemFree( header);
  1187.         HLock(pic);
  1188.       count= GetHandleSize(pic);
  1189.       afile->WriteData( *pic, count);
  1190.       afile->Close();
  1191.       HUnlock(pic);
  1192.       KillPicture ( (PicHandle)pic);
  1193.         } 
  1194.     fIsPrinting= false;        
  1195.     fRect= saverect;
  1196.     gCursor->arrow();
  1197.     return;
  1198. #endif
  1199.  
  1200. #ifdef WIN_MSWIN
  1201.   Nlm_RecT        pager, saverect, cellr;
  1202.   RECT  picrect;
  1203.     
  1204.     gCursor->watch();    
  1205.     saverect= fRect;
  1206.      fIsPrinting= kWritingAsPICT;
  1207.      Nlm_LoadRect( &cellr, 0, 0, fMaxCols, fMaxRows);
  1208.     this->GetCellRect( cellr, pager);
  1209.     fRect= pager;
  1210.   picrect.left= pager.left;
  1211.   picrect.top = pager.top;
  1212.   picrect.right = pager.right;
  1213.   picrect.bottom= pager.bottom;
  1214.     
  1215.     char* fname= (char*) afile->GetName();
  1216.     fname= (char*)DFileManager::FilenameFromPath(fname); // CreateMF fails for full path !?
  1217.     //fname= "test.wmf";
  1218.     
  1219. #if 1
  1220. //#ifdef WIN16
  1221.     HDC hdcMeta= CreateMetaFile(fname); // (fname)
  1222.     
  1223. #define MetaHandle HMETAFILE
  1224. #define MetaClose(x)  CloseMetaFile(x)
  1225. #define MetaDelete(x) DeleteMetaFile(x)
  1226. #define MetaGetData(a,b,c)  GetMetaFileBitsEx(a,b,c)
  1227.  
  1228. #else
  1229.   char  describes[120];
  1230.   char  titlebuf[80];
  1231.   char  *dp, *np, *ep;
  1232.   
  1233.   np= (char*)gApplication->Shortname();
  1234.   dp= describes;
  1235.   ep= dp + sizeof(describes) - 2;
  1236.   if (np) while (*np && dp < ep) { *dp++ = *np++; }
  1237.   *dp++ = 0;
  1238.   np= this->GetTitle(titlebuf, sizeof(titlebuf));
  1239.   if (np) while (*np && dp < ep) { *dp++ = *np++; }
  1240.   *dp++ = 0;
  1241.  
  1242.   // need pixel to .01 mm conversion for picrect !
  1243.   // need some needlessly complex SetMapMode, MapPoint, ResetMapMode...
  1244.   
  1245.     HDC hdcMeta= CreateEnhMetaFile( Nlm_currentHDC, NULL, &picrect, describes);
  1246. #define MetaHandle HENHMETAFILE
  1247. #define MetaClose(x)  CloseEnhMetaFile(x)
  1248. #define MetaDelete(x) DeleteEnhMetaFile(x)
  1249. #define MetaGetData(a,b,c)  GetEnhMetaFileBits(a,b,c)
  1250. #endif
  1251.  
  1252.   if (hdcMeta) { 
  1253.       POINT point;
  1254.       SIZE  size;
  1255.  
  1256.        HDC savehdc= Nlm_currentHDC;
  1257.       Nlm_currentHDC= hdcMeta;  
  1258.       SetMapMode( hdcMeta, MM_ANISOTROPIC);
  1259.         SetWindowOrgEx(hdcMeta, 0,0, &point);
  1260.         SetWindowExtEx(hdcMeta, picrect.right-picrect.left, 
  1261.                         picrect.bottom-picrect.top, &size);
  1262.  
  1263.       Nlm_ResetDrawingTools();
  1264.       
  1265.         // make update region large...
  1266.     if (Nlm_updateRgn != NULL)  
  1267.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1268.     Draw();  
  1269.       
  1270.       MetaHandle hmf = MetaClose( hdcMeta);
  1271.  
  1272. #ifdef WIN16
  1273.       // win16 code
  1274.       //HGLOBAL hgmf = GetMetaFileBits( hmf);
  1275. #else
  1276.       // win32 code
  1277.       ulong count, bufsize;
  1278.       METAFILEHEADER placeheader;
  1279.       bufsize= GetEnhMetaFileBits( hmf, 0, NULL);
  1280.       char* buf= (char*) MemNew( bufsize + 1);
  1281.       if ( GetEnhMetaFileBits( hmf, bufsize, (unsigned char*)buf) ) { 
  1282.         placeheader.key= 0x9AC6CDD7L;
  1283.         placeheader.hmf= 0;
  1284.         //c0 f4 90 f7 36 0b 66 08 is bbox rect that powerpnt made
  1285.         placeheader.boxtop = 0xf4c0; //picrect.top; //?? some neg.num?
  1286.         placeheader.boxleft= 0xf790; //picrect.left;  //?? some neg.num?
  1287.         placeheader.boxbottom= 0x0b36; //picrect.bottom;
  1288.         placeheader.boxright = 0x0866; //picrect.right;
  1289.         placeheader.inch= 576;
  1290.         placeheader.reserved= 0;
  1291.         placeheader.checksum= 0x5551;  
  1292.         CalcMFChecksum( &placeheader); // == 0x5551 ?
  1293.     
  1294.         afile->Delete();
  1295.         afile->Create("WMF","DCLAP"); 
  1296.           afile->Open("wb"); 
  1297.         count= 22; //!! not -> sizeof(placeheader);
  1298.         afile->WriteData( &placeheader, count);
  1299.         count= bufsize;
  1300.         afile->WriteData( buf, count);  
  1301.         afile->Close();
  1302.         }
  1303.       MemFree( buf);
  1304. #endif
  1305.  
  1306.       MetaDelete( hmf); // just deletes handle, not disk file !
  1307.       Nlm_currentHDC= savehdc;  
  1308.         }       
  1309.     fIsPrinting= false;        
  1310.     fRect= saverect;
  1311.     gCursor->arrow();
  1312.     return;
  1313. #endif
  1314.       
  1315.     Nlm_Message(MSG_OK,"DrawToPicture is not yet defined for this window system");
  1316. }
  1317.  
  1318.